package control;

import java.util.ArrayList;

import model.Observations;
import model.PAppGrid;
import model.PathOptions;

public class Viterbi {
	public void viterbi(Observations[] inputObs,PAppGrid states,double[] startProb,double[][] transitionProb,double[][] emissionProb,int playerIndex){
  	double[][] V = new double[inputObs.length][states.getSideSize()*states.getSideSize()];
  	int[] path = new int[inputObs.length];
  	double maxProbValue=0;
  	for(int i=0;i<states.getSideSize()*states.getSideSize();i++){
  		double tempProbValue=startProb[i]*emissionProb[inputObs[0].ordinal()][i];
  		V[0][i]=tempProbValue;
  		if(tempProbValue>maxProbValue){
  			maxProbValue=tempProbValue;
  		}
  	}
  	for(int observation=1;observation<inputObs.length-1;observation++){  		
  		double tempProbValue=0;
  		for(int destinationState=0;destinationState<states.getSideSize()*states.getSideSize();destinationState++){
  			maxProbValue=0;
  			for(int currentState=0;currentState<states.getSideSize()*states.getSideSize();currentState++){  
  				double 	vValue=V[observation-1][currentState],
  								tranProb=transitionProb[currentState][destinationState],
  								emiProb=emissionProb[inputObs[observation].ordinal()][destinationState];
  				tempProbValue=vValue*tranProb*emiProb;
  				if(tempProbValue>maxProbValue){
  					maxProbValue=tempProbValue; 	  			
  				}
  			}
  			V[observation][destinationState]=maxProbValue;
  		}
  	}
  	for(int destinationState=0;destinationState<states.getSideSize()*states.getSideSize();destinationState++){
			maxProbValue=0;		
			double 	vValue=V[inputObs.length-2][destinationState],
							tranProb=transitionProb[destinationState][destinationState],
							emiProb=emissionProb[inputObs[inputObs.length-1].ordinal()][destinationState];
			double probValue=vValue*tranProb*emiProb;
			V[inputObs.length-1][destinationState]=probValue;
		}
  	System.out.println("V");
  	printV(V);
  	System.out.println("Prueba");
  	ArrayList<Double> probabilities = new ArrayList<Double>();
  	ArrayList<Integer> st = new ArrayList<Integer>();
  	for(int observation=inputObs.length-1;observation>=0;observation--){  
  		maxProbValue=0;
  		probabilities.clear();
			st.clear();					
			for(int currentState=0;currentState<states.getSideSize()*states.getSideSize();currentState++){
				probabilities.add(V[observation][currentState]);
				st.add(currentState);				
  		}
			System.out.print(st+" ");
			System.out.println(probabilities+" ");
			
			double maxProb=0;
			for(Integer state:st){
				if(observation==inputObs.length-1){
					if(probabilities.get(state.intValue())>maxProb){
						maxProb=probabilities.get(state.intValue());
						path[observation]=state;
					}
					continue;
				}
				else if(transitionProb[state][path[observation+1]]!=0){
					if(probabilities.get(state.intValue())>maxProb){
						maxProb=probabilities.get(state.intValue());
						path[observation]=state;
					}
				}
			}
  	}
		printPath(path, states);
		System.out.println();
		System.out.println();
  	printV(V);
  }
  
  public void printPath(int[] path, PAppGrid grid){
  	System.out.println("Path");
  	for(int i=0;i<path.length;i++){
  		grid.getElement(path[i]).setActiveOption(PathOptions.SOLVED);
  		System.out.print(path[i]+"  ");
  	}
  	System.out.println();
  }
  public void printV(double[][] V){
  	System.out.println("V");
  	for (double[] row:V) {
			for (double column : row) {
  			System.out.print(column+"  ");
  		}
  		System.out.println();
  	}
  }
}
